package com.lwl.office.webeditor;

import com.lwl.office.webeditor.config.HeaderConfig;
import com.lwl.office.webeditor.tools.ConvertUtil;
import lombok.Data;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

/**
 * html解析上下文
 */
@Data
public class ParserContext {
    XWPFDocument word;
    XWPFParagraph paragraph;
    XWPFRun run;
    XWPFTable table;
    XWPFTableRow row;
    XWPFTableCell cell;
    CTHyperlink hyperlink;
    /**
     * 当前run节点的父节点类型
     */
    RPT rpt= RPT.WORD;

    Map<String,BigInteger> numberingMap = new HashMap<>();
    private boolean numberingInited;

    public BigInteger getNumbering(String name){
        if(!numberingInited){
            numberingInit();
            numberingInited=true;
        }
        return numberingMap.get(name);
    }

    /**
     * 初始化numbering
     */
    private void numberingInit() {
        XWPFNumbering numbering = word.getNumbering()==null?word.createNumbering():word.getNumbering();
        numbering.addAbstractNum(new XWPFAbstractNum(createCTAbstractNum(BigInteger.ZERO,STNumberFormat.DECIMAL,"%1.","宋体")));
        numberingMap.put("ol",numbering.addNum(BigInteger.ZERO));

        numbering.addAbstractNum(new XWPFAbstractNum(createCTAbstractNum(BigInteger.ONE,STNumberFormat.BULLET,"\uF06E","Wingdings")));
        numberingMap.put("ul",numbering.addNum(BigInteger.ONE));
    }

    private CTAbstractNum createCTAbstractNum(BigInteger abstractNumId
            ,STNumberFormat.Enum format
            ,String levelText,String fontFamily){
        CTAbstractNum abstractNum = CTAbstractNum.Factory.newInstance();
        abstractNum.setAbstractNumId(abstractNumId);

        CTLvl ctLvl = abstractNum.addNewLvl();
        ctLvl.setIlvl(BigInteger.ZERO);
        ctLvl.addNewNumFmt().setVal(format);;
        ctLvl.addNewStart().setVal(BigInteger.ONE);;
        ctLvl.addNewLvlJc().setVal(STJc.LEFT);;
        ctLvl.addNewLvlText().setVal(levelText);

        CTRPr rpr = ctLvl.isSetRPr() ? ctLvl.getRPr() : ctLvl.addNewRPr();
        CTFonts ctFonts = rpr.addNewRFonts();
        ctFonts.setAscii(fontFamily);
        ctFonts.setHAnsi(fontFamily);
        ctFonts.setHint(STHint.DEFAULT);
        return abstractNum;
    }
    public void setRpt(RPT rpt) {
        this.rpt = rpt==null? RPT.WORD:rpt;
    }

    public XWPFTable createTable(int rowNum, int cellNUm) {
        this.table = word.createTable(rowNum,cellNUm);
        return table;
    }

    public XWPFTableRow createRow() {
        this.row = table.createRow();
        return row;
    }

    public XWPFTableCell createCell() {
        this.cell = row.createCell();
        return cell;
    }

    public enum RPT{
        WORD,HYPERLINK,PARAGRAPH,CELL,LIST;
    }
    public ParserContext(){
        this.word = new XWPFDocument();
    }
    public XWPFRun createRun(){
        this.run = paragraph.createRun();
        return run;
    }
    public XWPFParagraph createParagraph(){
        switch (rpt){
            case CELL:
                this.paragraph = cell.addParagraph();
                break;
            default:
                this.paragraph = word.createParagraph();
                break;
        }
        return paragraph;
    }

    public XWPFStyles styles(){
        return word.getStyles()==null?word.createStyles():word.getStyles();
    }

    public XWPFStyle buildHeaderStyle(int level) {
        setBaseStyle();
        XWPFStyles styles = styles();
        XWPFStyle style = styles.getStyle(HeaderConfig.name + level);
        if(style==null){
            HeaderConfig config = HeaderConfig.of(level);
            CTStyle ctStyle = CTStyle.Factory.newInstance();
            ctStyle.setType(STStyleType.PARAGRAPH);
            ctStyle.setStyleId(level+"");
            ctStyle.setName(ConvertUtil.ctsOf(HeaderConfig.name+level));
            ctStyle.setBasedOn(ConvertUtil.ctsOf("a"));
            ctStyle.setNext(ConvertUtil.ctsOf("a"));
            ctStyle.setLink(ConvertUtil.ctsOf("10"));
            ctStyle.setUiPriority(ConvertUtil.ctnOf(9));
            //ppr
            CTPPrGeneral pPr = ctStyle.addNewPPr();
            pPr.addNewKeepNext();
            pPr.addNewKeepLines();
            CTSpacing spacing = pPr.addNewSpacing();
            spacing.setBefore(config.getSpacingBefore());
            spacing.setAfter(config.getSpacingAfter());
            spacing.setLine(config.getSpacingLine());
            spacing.setLineRule(STLineSpacingRule.AUTO);
            CTDecimalNumber otlv = pPr.addNewOutlineLvl();
            otlv.setVal(BigInteger.valueOf(level-1));
            //rpr
            CTRPr rpr = ctStyle.addNewRPr();
            rpr.addNewB();
            rpr.addNewBCs();
            rpr.addNewKern();
            CTHpsMeasure kern = rpr.addNewKern();
            kern.setVal(config.getKern());
            CTHpsMeasure sz = rpr.addNewSz();
            sz.setVal(config.getSz());
            CTHpsMeasure szCs = rpr.addNewSzCs();
            szCs.setVal(config.getSzCs());
            style = new XWPFStyle(ctStyle,styles);
            styles.addStyle(style);
        }
        return style;
    }

    /**
     * 设置超链接的样式
     */
    public XWPFStyle buildHyperlinkStype(){
        setBaseStyle();
        XWPFStyles styles = styles();
        XWPFStyle style = styles.getStyle("Hyperlink");
        if(style==null){
            CTStyle ctStyle = CTStyle.Factory.newInstance();
            ctStyle.setType(STStyleType.CHARACTER);
            ctStyle.setStyleId("Hyperlink");
            ctStyle.setName(ConvertUtil.ctsOf("Hyperlink"));
            ctStyle.setBasedOn(ConvertUtil.ctsOf("a0"));
            ctStyle.setUiPriority(ConvertUtil.ctnOf(99));
            //rpr
            CTRPr rpr = ctStyle.addNewRPr();
            CTColor ctColor = rpr.addNewColor();
            ctColor.setVal("0563C1");
            ctColor.setThemeColor(STThemeColor.HYPERLINK);
            CTUnderline ctUnderline = rpr.addNewU();
            ctUnderline.setVal(STUnderline.SINGLE);
            style = new XWPFStyle(ctStyle, styles);
            styles.addStyle(style);
        }
        return style;
    }
    /**
     * 构造基础类型a
     */
    private void setBaseStyle() {
        XWPFStyles styles = styles();
        if(styles.getStyle("a")==null){
            CTStyle ctStyle = CTStyle.Factory.newInstance();
            ctStyle.setType(STStyleType.PARAGRAPH);
            ctStyle.setStyleId("a");
            ctStyle.setName(ConvertUtil.ctsOf("Normal"));
            ctStyle.addNewQFormat();
            CTPPrGeneral pPr = ctStyle.addNewPPr();
            CTOnOff ctOnOff = CTOnOff.Factory.newInstance();
            pPr.setWidowControl(ctOnOff);
            CTJc ctJc = CTJc.Factory.newInstance();
            ctJc.setVal(STJc.BOTH);
            pPr.setJc(ctJc);
            XWPFStyle style = new XWPFStyle(ctStyle,styles);
            styles.addStyle(style);
        }
    }

    public CTHyperlink createHyperlink(String id) {
        this.hyperlink = paragraph.getCTP().addNewHyperlink();
        hyperlink.setId(id);
        return hyperlink;
    }
}
